﻿/*
 * Created by SharpDevelop.
 * User: Emanuel
 * Date: 29-05-2013
 * Time: 11:34
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using System.IO;

namespace Cifra
{
	/// <summary>
	/// Módulo de cifragem que tem como objetivo cifrar e decifrar texto.
	/// O algoritmo de cifragem é o algoritmo  de Rijndael : http://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndael.aspx
	/// </summary>
	public class Cifragem
	{
		private static readonly byte[] salt = Encoding.ASCII.GetBytes("segredos"); //salt para derivar a chave de acesso
		
		/// <summary>
		/// Método para decifrar texto
		/// </summary>
		/// <param name="texto para decifrar"></param>
		/// <param name="pass para decifrar"></param>
		/// <returns>texto decifrado</returns>
		public static string deCifrar(string texto, string pass) {
			var algoritmo = getAlgoritmo(pass);
			byte[] dBytes;
			using (ICryptoTransform dcif = algoritmo.CreateDecryptor(algoritmo.Key,algoritmo.IV)) {
				byte[] bytesCifrados = Convert.FromBase64String(texto);
				dBytes = cifraMemoria(bytesCifrados,dcif);
			}
			return Encoding.UTF8.GetString(dBytes);
		}
		
		/// <summary>
		/// Método para cifrar mensagem
		/// </summary>
		/// <param name="texto a cifrar"></param>
		/// <param name="pass para cifrar"></param>
		/// <returns>texto cifrado</returns>
		public static string cifrar(string texto, string pass) {
			var algoritmo = getAlgoritmo(pass);
			byte[] cBytes;
			using (ICryptoTransform cif = algoritmo.CreateEncryptor(algoritmo.Key,algoritmo.IV)) {
				byte[] bytesACifrar = Encoding.UTF8.GetBytes(texto);
				cBytes = cifraMemoria(bytesACifrar,cif);
			}
			return Convert.ToBase64String(cBytes);
		}
		
		/// <summary>
		/// Método para cifrar o texto na memoria
		/// </summary>
		/// <param name="data"></param>
		/// <param name="transform"></param>
		/// <returns>array de bytes</returns>
		private static byte[] cifraMemoria(byte[] data, ICryptoTransform transform) {
			MemoryStream mem = new MemoryStream();
			
			using (Stream stream = new CryptoStream(mem,transform,CryptoStreamMode.Write)) {
				stream.Write(data,0,data.Length);
			}
			return mem.ToArray();
		}
		
		/// <summary>
		/// Método para obter algoritmo de cifragem, ou seja, algoritmo Rijndael
		/// devidamente preparado.
		/// </summary>
		/// <param name="cifraPass"></param>
		/// <returns>Algoritmo Rijndael</returns>
		private static RijndaelManaged getAlgoritmo(string cifraPass) {
			
			var key = new Rfc2898DeriveBytes(cifraPass, salt);
			
			var algoritmo = new RijndaelManaged();
			int bytesChave = algoritmo.KeySize/8;
			int bytesIV = algoritmo.BlockSize/8;
			algoritmo.Key = key.GetBytes(bytesChave);
			algoritmo.IV = key.GetBytes(bytesIV);
			return algoritmo;
		}
		
	}
}